package com.qcxy.gzy.activity.v2;

import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;

import com.qcxy.gyz.consts.CMDConts;
import com.qcxy.gzy.activity.R;
import com.qcxy.gzy.activity.ReportActivity;
import com.qcxy.gzy.app.ComApplication;
import com.qcxy.gzy.bean.ComReceiveDataBean;
import com.qcxy.gzy.task.UploadTrainningDataTask;
import com.qxcy.gzy.util.DataCovertUtil;
import com.qxcy.gzy.util.NetWorkUtils;
import com.qxcy.gzy.util.PreferencesUtils;
import com.qxcy.gzy.util.SPUtils;
import com.qxcy.gzy.util.SerialPortUtils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;

import com.qcxy.gzy.activity.v4.SwitchEMActivity;

public class TrainingActivity extends SwitchEMActivity implements
        OnClickListener, SwitchEMActivity.SwitchEMListener {

    private TextView mTargetNumber;
    private TextView mWeight;
    private TextView showTargetNumber;
    private TextView mCalorieTv;
    private TextView mTimeTv;
    private int mShowWeight = 10;
    private static final int limitWeight = 30;//切换大电机临界值
    private static final int limitWeightSmall = 20;//切换小电机临界值
    private int gear = 0;//1或者10或者0
    private static final int WeightMax = 100, WeightMin = 0;

    private String activity;

    private boolean firstTime = true;
    private boolean startTime = false;

    private Timer weightTime = null;
    /**
     * 计算器
     */
    protected Calendar mCalendar = Calendar.getInstance();
    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
    boolean isUpLoad = false;// 是否上传过了
    protected JSONArray trainHistorys = new JSONArray();

    private int switchNum = 0;
    private boolean isNeedBig;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_v2_training);
        builder.append("锻炼页面--电机状态：").append(isEMRunning);
        if (isEMRunning) {
            builder.append("---当前运行电机：").append(runEMType == SerialPortUtils.ElectricMachineryBig ? "大电机" : "小电机");
        }
        builder.append("\n");
        mShowWeight = runEMType == SerialPortUtils.ElectricMachineryBig ? 30 : 10;
        String mUserName = SPUtils.getValueFromSharedFile(this, "userName", "");
        String mImgUrl = SPUtils.getValueFromSharedFile(this, "URL", "");
        System.out.println(mUserName + "---" + mImgUrl);
        TextView mTvTargetUnit = findViewById(R.id.tv_target_unit);
        TextView mTvTargetTraining = findViewById(R.id.tv_target_training_unit);

        Intent intent = getIntent();
        String data = intent.getStringExtra("Target");
        activity = intent.getStringExtra("Activity");
        switch (activity) {
            case "Number":
                mTvTargetUnit.setText(R.string.number_uint);
                mTvTargetTraining.setText(R.string.target_number_show);
                break;
            case "Time":
                mTvTargetUnit.setText(R.string.time_uint);
                mTvTargetTraining.setText(R.string.target_time_show);
                break;
            default:
                mTvTargetUnit.setText(R.string.calorie_uint);
                mTvTargetTraining.setText(R.string.target_calorie_show);
                break;
        }
        mTargetNumber = findViewById(R.id.tv_target_training);
        mTargetNumber.setText(data);
        findViewById(R.id.zl_js_1).setOnClickListener(this);
        findViewById(R.id.zl_zj_1).setOnClickListener(this);
        findViewById(R.id.zl_js_10).setOnClickListener(this);
        findViewById(R.id.zl_zj_10).setOnClickListener(this);
        findViewById(R.id.switch_em).setOnClickListener(this);
        findViewById(R.id.iv_back).setOnClickListener(this);
        mWeight = findViewById(R.id.tv_target_showweight);
        showTargetNumber = findViewById(R.id.text_show_number);
        mCalorieTv = findViewById(R.id.text_show_calorie);
        mTimeTv = findViewById(R.id.tv_target_showtime);

        findViewById(R.id.show_pause).setOnClickListener(this);
        findViewById(R.id.show_restart).setOnClickListener(this);

        mSendThread = new SendThread(getForceCMD(mShowWeight), false);
        mSendThread.start();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        closeTimer();
    }

    @Override
    public void onSwitch(final boolean isSuccess, final String message, final int type) {
        hideLoadingView();
        switchNum++;
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (isSuccess) {
                    switchNum = 0;
                    //暂存电机信息
                    PreferencesUtils.put(TrainingActivity.this, SerialPortUtils.CURRENT_EM, type);
                    toast("电机切换成功");
                    if (gear != 0) {
                        if (type == SerialPortUtils.ElectricMachineryBig) {
                            mShowWeight = mShowWeight + gear;
                        } else {
                            mShowWeight = mShowWeight - gear;
                        }
                        mWeight.setText(String.valueOf(mShowWeight));
                        // 定时开始
                        if (weightTime != null) {
                            weightTime.cancel();
                            weightTime.purge();
                            weightTime = null;
                        }
                        weightTime = new Timer();
                        weightTime.schedule(new weightChangeTask(), 2000);
                    }
                } else {
                    if (switchNum < 3) {
                        switchEM(isNeedBig);
                    } else {
                        switchNum = 0;
                        SerialPortUtils.showSerialDialog(TrainingActivity.this, "提示", message);
                    }
                }
            }
        });
        //日志相关
        builder.append("切换结果：").append(isSuccess ? "成功" : "失败").append("\n");
        if (!isSuccess) {
            builder.append("切换失败信息").append(message).append("\n");
        }
        builder.append("------------------------------------------------------------------------\n");
        SerialPortUtils.saveLocalDailyLog(builder.toString());
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.iv_back:
                SPUtils.setValueSharedFile(this, "Train_Number", mRealCounts + "");
                SPUtils.setValueSharedFile(this, "Train_Time", mCalendar.get(Calendar.MINUTE) + "");
                SPUtils.setValueSharedFile(this, "Train_Calorie", String.format(Locale.CHINA, "%.1f", calorie));
                uploadTrainData();
                Intent intent = new Intent(TrainingActivity.this, ReportActivity.class);
                startActivity(intent);
                TrainingActivity.this.finish();
                break;
            case R.id.switch_em:
                gear = 0;
                int current = (int) PreferencesUtils.get(this, SerialPortUtils.CURRENT_EM, SerialPortUtils.ElectricMachineryBig);
                String message = String.format(Locale.CHINA, "是否切换为%s电机", current == SerialPortUtils.ElectricMachineryBig ? "小" : "大");
                switchDialog(current == SerialPortUtils.ElectricMachinerySmall, message);
                break;
            case R.id.zl_zj_1:
                gear = 1;
                if (isEMSwitching) return;
                if (mShowWeight < limitWeight && (mShowWeight + 1) >= limitWeight && runEMType == SerialPortUtils.ElectricMachinerySmall) {
                    autoSwitch(true);
                } else {
                    if (mShowWeight <= WeightMax) {
                        mShowWeight++;
                        mWeight.setText(String.valueOf(mShowWeight));
                        // 定时开始
                        if (weightTime != null) {
                            weightTime.cancel();
                            weightTime.purge();
                            weightTime = null;
                        }
                        weightTime = new Timer();
                        weightTime.schedule(new weightChangeTask(), 2000);
                    } else {
                        toast(R.string.max_weight);
                    }
                }
                break;
            case R.id.zl_js_1:
                gear = 1;
                if (isEMSwitching) return;
                if (mShowWeight >= limitWeightSmall && (mShowWeight - 1) < limitWeightSmall && runEMType == SerialPortUtils.ElectricMachineryBig) {
                    autoSwitch(false);
                } else {
                    if (mShowWeight > WeightMin) {
                        mShowWeight--;
                        mWeight.setText(String.valueOf(mShowWeight));
                        // 定时开始
                        if (weightTime != null) {
                            weightTime.cancel();
                            weightTime.purge();
                            weightTime = null;
                        }
                        weightTime = new Timer();
                        weightTime.schedule(new weightChangeTask(), 2000);
                    } else {
                        toast(R.string.min_weight);
                    }
                }
                break;
            case R.id.zl_zj_10:
                gear = 10;
                if (isEMSwitching) return;
                if (mShowWeight < limitWeight && (mShowWeight + 10) >= limitWeight && runEMType == SerialPortUtils.ElectricMachinerySmall) {
                    autoSwitch(true);
                } else {
                    if (mShowWeight <= WeightMax) {
                        if (mShowWeight + gear >= WeightMax) {
                            mShowWeight = WeightMax;
                        } else {
                            mShowWeight = mShowWeight + gear;
                        }
                        mWeight.setText(String.valueOf(mShowWeight));
                        // 定时开始
                        if (weightTime != null) {
                            weightTime.cancel();
                            weightTime.purge();
                            weightTime = null;
                        }
                        weightTime = new Timer();
                        weightTime.schedule(new weightChangeTask(), 2000);
                    } else {
                        toast(R.string.max_weight);
                    }
                }
                break;
            case R.id.zl_js_10:
                gear = 10;
                if (isEMSwitching) return;
                if (mShowWeight >= limitWeightSmall && (mShowWeight - 10) < limitWeightSmall && runEMType == SerialPortUtils.ElectricMachineryBig) {
                    autoSwitch(false);
                } else {
                    if (mShowWeight > WeightMin) {
                        if (mShowWeight > gear) {
                            mShowWeight = mShowWeight - gear;
                        } else {
                            mShowWeight = 1;
                        }
                        mWeight.setText(String.valueOf(mShowWeight));
                        // 定时开始
                        if (weightTime != null) {
                            weightTime.cancel();
                            weightTime.purge();
                            weightTime = null;
                        }
                        weightTime = new Timer();
                        weightTime.schedule(new weightChangeTask(), 2000);
                    } else {
                        toast(R.string.min_weight);
                    }
                }
                break;
            case R.id.show_pause:
                if (!"00:00".equals(mTimeTv.getText().toString())) {
                    int minute = mCalendar.get(Calendar.MINUTE);
                    int second = mCalendar.get(Calendar.SECOND);
                    closeTimer();
                    mCalendar.set(Calendar.HOUR_OF_DAY, 0);
                    mCalendar.set(Calendar.MINUTE, minute);
                    mCalendar.set(Calendar.SECOND, second);
                    startTime = true;
                }
                break;
            case R.id.show_restart:
                if (!"00:00".equals(mTimeTv.getText().toString())) {
                    resetCalendar();
                    closeTimer();
                    mRealCounts = 0;
                    calorie = 0;
                    showTargetNumber.setText(String.valueOf(mRealCounts));
                    mCalorieTv.setText(String.format(Locale.CHINA, "%.1f", calorie));
                    mTimeTv.setText(R.string.init_time);
                    firstTime = true;
                }
                break;
            default:
                break;
        }
    }

    private String getResString(int res) {
        return getResources().getString(res);
    }

    private void autoSwitch(final boolean isBig) {
        isNeedBig = isBig;
        boolean isCurrentBig = runEMType == SerialPortUtils.ElectricMachineryBig;
        if (isCurrentBig == isBig) return;
        switchEM(isBig);
    }

    private void showSwitchBig(final boolean isBig) {
        isNeedBig = isBig;
        boolean isCurrentBig = runEMType == SerialPortUtils.ElectricMachineryBig;
        if (isCurrentBig == isBig) return;
        String message = getResString(isBig ? R.string.switchEMMsg01 : R.string.switchEMMsg02);
        message = String.format(Locale.CHINA, message, isBig ? (limitWeight - 1) : limitWeight);
        switchDialog(isBig, message);
    }

    private void switchDialog(final boolean isBig, String message) {
        SerialPortUtils.showSwitchDialog(TrainingActivity.this, getResString(R.string.switchEM), message, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                switchEM(isBig);
            }
        });
    }

    private void switchEM(final boolean isBig) {
        closeSendThread();
        if (isBig) {
            //切换至大电机
            switchToEMBig();
        } else {
            //切换至小电机
            switchToEMSmall();
        }
    }

    @Override
    protected void onDataReceived(ComReceiveDataBean ComRecData) {
        if (isEMSwitching && ComRecData.bRec.length < 9) {
            super.onDataReceived(ComRecData);
        } else {
            if (ComRecData.getCRC(ComRecData.bRec).equals("0")) {
                String res = DataCovertUtil.ByteArrToHex(ComRecData.bRec);
                if (DataCovertUtil.HexToInt(DataCovertUtil
                        .ByteArrToHex(ComRecData.bRec).substring(2, 4)) == 3) { // control指的返回的命令区分码
                    // 实时值
                    // final int weight = DataCovertUtil
                    // .HexToInt(res.substring(6, 10));
                    final int distance = DataCovertUtil.HexToInt(res.substring(10,
                            14));
                    if (distance > 150) {
                        if (firstTime) {
                            resetCalendar();
                            showClock(mTimeTv);
                            firstTime = false;
                        }
                        if (startTime) {
                            showClock(mTimeTv);
                            startTime = false;
                        }
                    }
                    if (distance >= 1500) { // 检测到距离大于60%最大距离时
                        mStatus = 1; // 拉伸状态变为1
                        if (distance4Calorie < distance) {
                            distance4Calorie = distance;
                        }
                    }
                    // 拉伸状为1并且 检测到距离小于30%最大距离时拉伸状态变为
                    if (mStatus == 1 && distance < 1500) {
                        mRealCounts++; // 次数 + 1
                        mStatus = 0; // 拉伸状态清除

                        if (distance4Calorie >= 1500 && distance4Calorie < 2000) {
                            calorie = calorie + (mShowWeight / (180 + (Math.random() * 40)));
                        } else if (distance4Calorie >= 2000 && distance4Calorie < 3000) {
                            calorie = calorie + (mShowWeight / (130 + (Math.random() * 40)));
                        } else {
                            calorie = calorie + (mShowWeight / (80 + (Math.random() * 40)));
                        }
                    }
                    switch (activity) {
                        case "Number":
                            if (mRealCounts == Integer.parseInt(mTargetNumber.getText()
                                    .toString())) {
                                if (!isUpLoad) {
                                    // uploadTrainData();
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            showTargetNumber.setText(String.valueOf(mRealCounts));
                                            mCalorieTv.setText(String.format(Locale.CHINA, "%.1f", calorie));
                                            Toast.makeText(TrainingActivity.this, R.string.finish, Toast.LENGTH_SHORT).show();
                                        }
                                    });
                                    isUpLoad = true;
                                }
                            }
                            break;
                        case "Time":
                            if (mCalendar.get(Calendar.MINUTE) == Integer
                                    .parseInt(mTargetNumber.getText().toString())) {
                                if (!isUpLoad) {
                                    // uploadTrainData();
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            showTargetNumber.setText(String.valueOf(mRealCounts));
                                            mCalorieTv.setText(String.format(Locale.CHINA, "%.1f", calorie));
                                            Toast.makeText(TrainingActivity.this, R.string.finish, Toast.LENGTH_SHORT).show();
                                        }
                                    });
                                    isUpLoad = true;
                                }
                            }
                            break;
                        default:
                            if ((int) calorie >= Integer.parseInt(mTargetNumber
                                    .getText().toString())) {
                                if (!isUpLoad) {
                                    // uploadTrainData();
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            showTargetNumber.setText(String.valueOf(mRealCounts));
                                            mCalorieTv.setText(String.format(Locale.CHINA, "%.1f", calorie));
                                            Toast.makeText(TrainingActivity.this, R.string.finish, Toast.LENGTH_SHORT).show();
                                        }
                                    });
                                    isUpLoad = true;
                                }
                            }
                            break;
                    }

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            showTargetNumber.setText(String.valueOf(mRealCounts));
                            mCalorieTv.setText(String.format(Locale.CHINA, "%.1f", calorie));
                        }
                    });
                }
            }
        }
    }

    /**
     * 获得力量数据
     *
     * @param maxStrength 用户测定最大力量，单位牛顿
     */
    protected List<byte[]> getForceCMD(int maxStrength) {
        List<String> forceList;
        StringBuilder sDistance_D2 = new StringBuilder(); // 存放写入力量寄存器2命令
        StringBuilder sDistance_D3 = new StringBuilder(); // 存放写入力量寄存器2命令
        StringBuilder sDistance_D4 = new StringBuilder(); // 存放写入力量寄存器2命令
        StringBuilder sDistance_D5 = new StringBuilder(); // 存放写入力量寄存器2命令
        int distance_3; // 存放距离寄存器3的值
        List<byte[]> cmdList = new ArrayList<>(); // 命令列表
        List<String> forceHeadList = new ArrayList<>(); // 写入力量命令列表
        forceHeadList.add(CMDConts.CMD_WRITE_REIGSTER_F1); // 添加命令头部
        forceHeadList.add(CMDConts.CMD_WRITE_REIGSTER_F2);
        forceHeadList.add(CMDConts.CMD_WRITE_REIGSTER_F3);
        forceHeadList.add(CMDConts.CMD_WRITE_REIGSTER_F4);
        forceHeadList.add(CMDConts.CMD_WRITE_REIGSTER_F5);
        cmdList.add(CMDConts.CMD_WRITE_REIGSTER_F0);

        forceList = getConstantForce(maxStrength);

        if (forceList != null) {
            for (int i = 0; i < forceHeadList.size(); i++) {
                // 获得并添加CRC校验码
                String sBuilder = forceHeadList.get(i) + // 添加头部
                        forceList.get(i);
                cmdList.add(DataCovertUtil.getCRC(DataCovertUtil
                        .HexToByteArr(sBuilder // 添加力量值
                        )));
            }
        }
        distance_3 = (80 + MAX_DISTANCE) / 2; // 计算距离寄存器D3的值
        sDistance_D2.append(CMDConts.CMD_WRITE_REIGSTER_D2); // 添加头部
        sDistance_D2.append(DataCovertUtil.get4LenString(Integer
                .toHexString((80 + distance_3) / 2))); // 计算并添加距离值
        sDistance_D3.append(CMDConts.CMD_WRITE_REIGSTER_D3); // 添加头部
        sDistance_D3.append(DataCovertUtil.get4LenString(Integer
                .toHexString(distance_3))); // 添加距离值
        sDistance_D4.append(CMDConts.CMD_WRITE_REIGSTER_D4); // 添加头部
        sDistance_D4.append(DataCovertUtil.get4LenString(Integer
                .toHexString((distance_3 + MAX_DISTANCE) / 2)));// 添加距离值
        sDistance_D5.append(CMDConts.CMD_WRITE_REIGSTER_D5); // 添加头部
        sDistance_D5.append(DataCovertUtil.get4LenString(Integer
                .toHexString(MAX_DISTANCE))); // 添加距离值
        cmdList.add(CMDConts.CMD_WRITE_REIGSTER_D0); // 添加距离寄存器D0的命令
        cmdList.add(CMDConts.CMD_WRITE_REIGSTER_D1); // 添加距离寄存器D1的命令
        cmdList.add(DataCovertUtil.getCRC(DataCovertUtil
                .HexToByteArr(sDistance_D2.toString()))); // 计算并添加距离寄存器D2命令的CRC校验码
        cmdList.add(DataCovertUtil.getCRC(DataCovertUtil
                .HexToByteArr(sDistance_D3.toString()))); // 计算并添加距离寄存器D3命令的CRC校验码
        cmdList.add(DataCovertUtil.getCRC(DataCovertUtil
                .HexToByteArr(sDistance_D4.toString()))); // 计算并添加距离寄存器D4命令的CRC校验码
        cmdList.add(DataCovertUtil.getCRC(DataCovertUtil
                .HexToByteArr(sDistance_D5.toString()))); // 计算并添加距离寄存器D5命令的CRC校验码
        cmdList.add(CMDConts.CMD_READ_REGISTER_3_4); // 添加读取寄存器3、4命令
        return cmdList;
    }

    /**
     * 获得恒力力量
     *
     * @param maxStrength maxStrength
     */
    private List<String> getConstantForce(int maxStrength) {
        List<String> list = new ArrayList<>();
        String force = DataCovertUtil.get4LenString(Integer
                .toHexString((int) (33.33 * maxStrength))); // 获得四位字符串型力量的值
        list.add(force);
        list.add(force);
        list.add(force);
        list.add(force);
        list.add(force);
        return list;
    }

    private void uploadTrainData() {
        String openid = SPUtils.getValueFromSharedFile(this, "OpenId", "");
        if (!TextUtils.isEmpty(openid)) {
            String mac = ComApplication.getLocalMacAddressFromWifiInfo();
            try {
                JSONObject trainHis = new JSONObject();
                trainHis.putOpt("times", String.valueOf(mRealCounts));
                trainHis.putOpt("calorie", String.valueOf(calorie));
                if (mRealCounts == 0) {
                    trainHis.putOpt("duration", 0);
                } else {
                    trainHis.putOpt(
                            "duration",
                            mCalendar.get(Calendar.MINUTE) * 60
                                    + mCalendar.get(Calendar.SECOND));
                }
                trainHis.putOpt("strength", mShowWeight);
                trainHis.putOpt("time", String.valueOf(formatter.format(new Date())));
                trainHistorys.put(trainHis);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            if (trainHistorys.length() > 0) {
                if (NetWorkUtils.isNetworkConnected(this)) {
                    if (!TextUtils.isEmpty(openid)) {// 用户存在时进行上传
                        new UploadTrainningDataTask(this).execute(openid, mac, "3", trainHistorys);
                    }
                } else {
                    Toast.makeText(this, R.string.scan_noNet, Toast.LENGTH_LONG).show();
                }
            } else {
                Toast.makeText(this, R.string.scan_noDate, Toast.LENGTH_LONG).show();
            }
        }
    }

    private Timer timer;

    private void showClock(TextView tv) {
        timer = new Timer();
        timer.schedule(new TrainTask(tv), 1000, 1000);
    }

    private void resetCalendar() {
        mCalendar.set(Calendar.HOUR_OF_DAY, 0);
        mCalendar.set(Calendar.MINUTE, 0);
        mCalendar.set(Calendar.SECOND, 0);
    }

    private class TrainTask extends TimerTask {
        TrainTask(TextView tv) {
            mTimeTv = tv;
        }

        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                public void run() {
                    // 每次秒数+1
                    mCalendar.add(Calendar.SECOND, 1);
                    String s = DataCovertUtil.get2LenString(mCalendar.get(Calendar.MINUTE)) +
                            ":" + DataCovertUtil.get2LenString(mCalendar.get(Calendar.SECOND));
                    mTimeTv.setText(s);
                }
            });
        }
    }

    private class weightChangeTask extends TimerTask {
        @Override
        public void run() {
            closeSendThread();
            mSendThread = new SendThread(getForceCMD(mShowWeight), false);
            mSendThread.start();
        }
    }

    private void closeTimer() {
        if (timer != null) {
            timer.cancel();
            timer.purge();
            timer = null;
        }
        if (weightTime != null) {
            weightTime.cancel();
            weightTime.purge();
            weightTime = null;
        }
    }
}